#include "ap_log_app.h"
#include <rtthread.h>
#include <rtdevice.h>
#include "manager_task.h"
#include "config_api.h"

#define DBG_ENABLE
#define DBG_SECTION_NAME "[AP]"
#include "uc_log.h"

#define RINGBUFF_SIZE 1024
static struct rt_ringbuffer *ap_log_ringbuffer = RT_NULL;

/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;

static rt_err_t ap_log_app_rx_indicate(rt_device_t dev, rt_size_t size)
{
    unsigned int data_len = 0;
    unsigned char uart_recv_buf[RINGBUFF_SIZE];

    data_len = rt_device_read(dev, 0, &uart_recv_buf[0], size);
    if (data_len > 0)
    {
        rt_ringbuffer_put(ap_log_ringbuffer, (const rt_uint8_t *)uart_recv_buf, data_len);
    }

    /* 串口接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx_sem);
}

static void ap_log_app_task(void *parameter)
{
    int ret = RT_ERROR;
    unsigned short data_len = 0;
    unsigned char uart_recv_buf[256];
    struct serial_configure cfg = AP_LOG_CONFIG;
    gw_log_switch_cfg_t *gw_log_switch_cfg = uc_static_get_gateway_log_switch_cfg();

    rt_device_t device = rt_device_find(AP_LOG_UART);
    if (device == RT_NULL)
    {
        TRACE_E("ap_log_app find device %s failed", AP_LOG_UART);
        return;
    }

    ret = rt_device_control(device, RT_DEVICE_CTRL_CONFIG, &cfg);
    RT_ASSERT(ret == RT_EOK);

    /* using DMA mode first */
    ret = rt_device_open(device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
    /* using interrupt mode when DMA mode not supported */
    if (ret == -RT_EIO)
    {
        TRACE_W("ap_log_app using rx interrupt mode");
        ret = rt_device_open(device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
    }
    RT_ASSERT(ret == RT_EOK);

    /* 初始化 ringbuffer */
    ap_log_ringbuffer = rt_ringbuffer_create(RINGBUFF_SIZE);
    RT_ASSERT(ap_log_ringbuffer != RT_NULL);

    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_PRIO);
    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(device, ap_log_app_rx_indicate);

    data_len = 0;
    while (1)
    {
        /* 阻塞等待接收信号量，等到信号量后再次读取数据 */
        rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        do
        {
            if (0 == rt_ringbuffer_getchar(ap_log_ringbuffer, &uart_recv_buf[data_len]))
            {
                break;
            }

            if (uart_recv_buf[data_len] == '\n')
            {
                uart_recv_buf[data_len] = '\0';
                if (uart_recv_buf[data_len - 1] == '\r')
                {
                    uart_recv_buf[data_len - 1] = '\0';
                }
                if (gw_log_switch_cfg->ap_log_output != 0)
                {
                    TRACE_AP("%s", uart_recv_buf);
                }
                rt_memset(uart_recv_buf, 0, sizeof(uart_recv_buf));
                data_len = 0;
            }
            else
            {
                data_len += 1;
            }
        } while (1);
    }
}

int ap_log_app_init(void)
{
    void *ap_log_handle = RT_NULL;
    // 创建串口任务
    if (0 != manager_thread_create(&ap_log_handle, "ap_log", ap_log_app_task, RT_NULL, 512, RT_THREAD_PRIORITY_MAX - 3, 5))
    {
        TRACE_E("ap_log_app task create error");
        return -RT_ERROR;
    }

    return rt_thread_startup((rt_thread_t)ap_log_handle);
}

INIT_APP_EXPORT(ap_log_app_init);
